package org.example.interceptor;

import org.example.annotation.ApiSecurity;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Description:
 * 在HandlerInterceptorAdapter中主要提供了以下的方法：
 * preHandle：在方法被调用前执行。在该方法中可以做类似校验的功能。如果返回true，则继续调用下一个拦截器。
 * 如果返回false，则中断执行，也就是说我们想调用的方法 不会被执行，但是你可以修改response为你想要的响应。
 * postHandle：在方法执行后调用。
 * afterCompletion：在整个请求处理完毕后进行回调，也就是说视图渲染完毕或者调用方已经拿到响应。
 * @author shenguangyang
 */
public class ApiSecurityInterceptor extends HandlerInterceptorAdapter {
    /**
     * 处理器处理之前调用
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
                             Object handler) throws Exception {

        ApiSecurity apiSecurity = findApiSecurityAnnotation(handler);

        //获取注解中的值
        if (apiSecurity == null) {
            return true;
        }
        String value = apiSecurity.value();
        System.out.println(value);
        return true;
    }

    /**
     * 在方法执行后调用
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        //在方法执行后调用
    }

    /**
     * 在整个请求处理完毕后进行回调
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //在整个请求处理完毕后进行回调，也就是说视图渲染完毕或者调用方已经拿到响应

        //日志肯定是在afterCompletion之后记录的，否则中途失败了，也记录了，那就扯淡了。
        // 一定是程序正常跑完后，我们记录下那些对数据库做个增删改的操作日志进数据库。
        // 所以我们只需要继承HandlerInterceptorAdapter，并重写afterCompletion一个方法即可，
        // 因为preHandle默认是true。
    }

    /**
     * 处理器处理之前调用
     */
    @Override
    public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    }

    /**
     * 根据handlerMethod返回注解信息
     *
     * @param handler 方法对象
     * @return ApiSecurity注解
     */
    private ApiSecurity findApiSecurityAnnotation(Object handler) {
        if (!(handler instanceof HandlerMethod)) {
            return null;
        }
        HandlerMethod handlerMethod = (HandlerMethod)handler;
        //在方法上寻找注解
        ApiSecurity apiSecurity = handlerMethod.getMethodAnnotation(ApiSecurity.class);
        if (apiSecurity == null) {
            //在类上寻找注解
            apiSecurity = handlerMethod.getBeanType().getAnnotation(ApiSecurity.class);
        }
        return apiSecurity;
    }
}
